Skip to content

ROS2 Humble 跨设备 DDS 组播通信配置指南

适用场景:在 Windows 侧 WSL 的 RViz2 中实时显示远端 Jetson Xavier NX 上 ROS2 发布的话题(LiDAR 点云、TF、地图等)。


一、网络拓扑总览

本方案涉及多层嵌套环境,从外到内的完整链路如下:

┌─────────────────────────────────────────────────────────────────────────┐
│  Windows 11 主机                                                        │
│  ┌───────────────────────────────────────────────────────┐              │
│  │  WSL2 - Ubuntu 22.04                                  │              │
│  │  ┌─────────────────────────────────────────┐          │              │
│  │  │  ROS2 Humble                            │          │              │
│  │  │  - RViz2(可视化)                        │          │              │
│  │  │  - ros2 topic list / echo(调试)         │          │              │
│  │  │  网卡: eth2  IP: 192.168.3.182           │          │              │
│  │  └─────────────────────────────────────────┘          │              │
│  └───────────────────────────────────────────────────────┘              │
│                          │                                              │
│                     WiFi 局域网                                          │
│                    192.168.3.0/24                                        │
│                          │                                              │
└──────────────────────────┼──────────────────────────────────────────────┘

┌──────────────────────────┼──────────────────────────────────────────────┐
│  Jetson Xavier NX(宿主机 Ubuntu 20.04)                                 │
│  网卡: wlan0  IP: 192.168.3.214                                         │
│  ┌───────────────────────────────────────────────────────┐              │
│  │  Docker 容器(--network=host)                         │              │
│  │  Ubuntu 22.04                                         │              │
│  │  ┌─────────────────────────────────────────┐          │              │
│  │  │  ROS2 Humble                            │          │              │
│  │  │  - 各类节点(LiDAR驱动、导航、定位等)     │          │              │
│  │  │  - 话题发布者                             │          │              │
│  │  │  共享宿主机网络栈(host 模式)             │          │              │
│  │  └─────────────────────────────────────────┘          │              │
│  └───────────────────────────────────────────────────────┘              │
└─────────────────────────────────────────────────────────────────────────┘

关键点说明:

  • WSL2 的 eth2 网卡已桥接到宿主机的物理 WiFi 网卡,与 Jetson 处于同一个 192.168.3.0/24 子网,可以互相 ping 通。
  • Jetson 侧 Docker 使用 --network=host 模式,容器直接共享宿主机的网络栈,无需额外端口映射。
  • 两侧 ROS2 均使用默认的 FastDDS 中间件,通过 UDP 组播(Multicast) 进行节点自动发现。

二、DDS 组播发现原理(简述)

ROS2 默认使用 FastDDS 作为 DDS 中间件,节点发现依赖 RTPS 协议的组播机制

  • 每个 ROS2 节点启动时,会向组播地址 239.255.0.1 的对应端口发送 Participant Discovery Protocol (PDP) 公告。
  • 同一 ROS_DOMAIN_ID 下的所有节点监听同一个端口,因此能互相发现。
  • 发现端口的计算公式为:
discovery_port = 7400 + 250 × ROS_DOMAIN_ID

例如 ROS_DOMAIN_ID=6 时,发现端口为 7400 + 250 × 6 = 8900

组播能通,节点就能互相发现——不需要任何额外的 DDS XML 配置。


三、前置条件检查清单

在开始配置之前,逐项确认以下条件:

3.1 网络互通

bash
# WSL 中 ping Jetson
ping 192.168.3.214

# Jetson 中 ping WSL
ping 192.168.3.182

双向均应 0% packet loss。如果 ping 不通,请先解决基础网络问题(WiFi 连接、WSL 网络模式等)。

3.2 Docker 网络模式

在 Jetson 宿主机上确认容器使用 host 网络:

bash
docker inspect <容器> | grep NetworkMode

输出应为:

"NetworkMode": "host",

如果不是 host 模式,容器内的组播包无法直接通过宿主机的 wlan0 发出,需要改用 --network=host 重新创建容器。

3.3 DDS 中间件

两侧均应使用默认的 FastDDS(不需要手动安装或切换):

bash
echo $RMW_IMPLEMENTATION

无输出或输出 rmw_fastrtps_cpp 均为正确状态。如果输出了其他值(如 rmw_cyclonedds_cpp),需要统一为同一种 DDS 实现。


四、配置步骤

4.1 统一 ROS_DOMAIN_ID

两侧必须使用完全相同的 ROS_DOMAIN_ID,否则节点发现会在不同的端口上进行,永远无法互通。

WSL 侧(~/.bashrc):

bash
echo 'export ROS_DOMAIN_ID=6' >> ~/.bashrc
source ~/.bashrc

Jetson Docker 侧(容器内 ~/.bashrc):

bash
echo 'export ROS_DOMAIN_ID=6' >> ~/.bashrc
source ~/.bashrc

验证:

bash
echo $ROS_DOMAIN_ID
# 两侧都应输出: 6

注意:ROS_DOMAIN_ID 的值可以是 0~232 之间的任意整数,只要两边一致即可。如果你的局域网中有其他 ROS2 设备不想互相干扰,可以选一个独特的数字。

4.2 关闭 ROS_LOCALHOST_ONLY

这个环境变量如果被设为 1,DDS 将只在本机通信,彻底屏蔽跨设备发现。

两侧都执行:

bash
echo 'export ROS_LOCALHOST_ONLY=0' >> ~/.bashrc
source ~/.bashrc

验证:

bash
echo $ROS_LOCALHOST_ONLY
# 应输出: 0(或为空,空等价于 0)

4.3 放行 Windows 防火墙(关键步骤)

这是整个配置中最容易被忽略也最关键的一步。

WSL2 的入站网络流量需要经过 Windows 防火墙,而 Windows 防火墙默认会拦截入站的 UDP 组播包,导致 WSL 中的 ROS2 节点无法收到 Jetson 发出的 DDS 发现公告。

症状表现为:Jetson 侧的 ros2 topic list 能看到 WSL 的话题,但 WSL 侧看不到 Jetson 的话题(单向不通)。

在 Windows 上以管理员身份打开 PowerShell,执行以下命令:

powershell
# 放行 DDS 发现端口(DOMAIN_ID=6 对应 8900)
# 如果你使用其他 DOMAIN_ID,请按公式 7400+250*ID 计算端口
New-NetFirewallRule -DisplayName "ROS2 DDS Discovery Inbound" `
  -Direction Inbound `
  -Protocol UDP `
  -LocalPort 7400-7500,8900-9000 `
  -Action Allow

# 放行 DDS 数据传输(用户流量端口范围较大)
New-NetFirewallRule -DisplayName "ROS2 DDS UserTraffic Inbound" `
  -Direction Inbound `
  -Protocol UDP `
  -LocalPort 7400-65535 `
  -Action Allow

如果你不想精细管理端口,也可以用更简单粗暴的方式——直接放行所有 WSL 入站流量:

powershell
New-NetFirewallRule -DisplayName "WSL Inbound Allow All" `
  -Direction Inbound `
  -Program "C:\Windows\System32\wsl.exe" `
  -Action Allow

验证防火墙规则是否生效:

powershell
Get-NetFirewallRule -DisplayName "ROS2*" | Format-Table Name, DisplayName, Enabled, Action

五、验证通信

5.1 组播包抓包验证

在 WSL 中使用 tcpdump 确认能收到 Jetson 发出的组播包:

bash
# 安装 tcpdump(如果没有)
sudo apt install -y tcpdump

# 抓取 DDS 发现端口的 UDP 包(DOMAIN_ID=6 → 端口 8900)
sudo tcpdump -i eth2 udp port 8900 -nn

同时在 Jetson Docker 中随便发布一个话题:

bash
source /opt/ros/humble/setup.bash
ros2 topic pub /test_topic std_msgs/msg/String "data: 'hello from jetson'" --rate 1

预期结果: tcpdump 中应同时出现来自 192.168.3.182(WSL)和 192.168.3.214(Jetson)的 UDP 包。如果只有 WSL 自己的包,说明防火墙仍在拦截,请回到第 4.3 步检查。

5.2 ROS2 话题验证

bash
# WSL 中
source /opt/ros/humble/setup.bash

# 列出所有可见话题
ros2 topic list

# 应能看到 /test_topic

# 查看话题数据
ros2 topic echo /test_topic

输出应为:

data: hello from jetson
---
data: hello from jetson
---

5.3 启动 RViz2

bash
source /opt/ros/humble/setup.bash
rviz2

在 RViz2 中:

  1. 左下角点击 Add
  2. 选择 By topic 标签页
  3. 展开列表,即可看到 Jetson 发布的所有话题
  4. 选中需要的话题类型(如 LaserScan、PointCloud2、TF、Map 等)点击 OK 添加

六、常见问题排查

Q1:ros2 topic list 只显示 /parameter_events/rosout

原因:DDS 节点发现失败。按以下顺序排查:

  1. 检查 ROS_DOMAIN_ID 两侧是否一致
  2. 检查 ROS_LOCALHOST_ONLY 是否为 0
  3. 用 tcpdump 抓包确认组播包是否到达
  4. 检查 Windows 防火墙是否已放行

Q2:能看到话题但 ros2 topic echo 没有数据

原因:DDS 发现成功但数据传输被拦截。数据走的是另一组 UDP 端口。确保防火墙放行了足够宽的端口范围(建议 7400-65535 全放行)。

Q3:RViz2 显示话题但画面不更新或严重延迟

可能原因:

  • WiFi 带宽不够(特别是点云数据量很大时),可以在发布侧降低频率或降采样
  • QoS 不匹配,尝试在 RViz2 的话题设置中将 Reliability 改为 Best Effort

Q4:Docker 容器重启后配置丢失

如果容器不是用 docker commit 保存的,~/.bashrc 中的环境变量会丢失。建议在 docker run 命令中直接传入:

bash
docker run -it --network=host \
  -e ROS_DOMAIN_ID=6 \
  -e ROS_LOCALHOST_ONLY=0 \
  <镜像> /bin/bash

或写入 Dockerfile:

dockerfile
ENV ROS_DOMAIN_ID=6
ENV ROS_LOCALHOST_ONLY=0

Q5:如何确认 DDS 发现端口号

discovery_port = 7400 + 250 × ROS_DOMAIN_ID
ROS_DOMAIN_ID发现端口
07400
17650
68900
109900

七、环境变量速查

以下环境变量建议写入两侧的 ~/.bashrc,确保每次启动终端自动生效:

bash
# ====== ROS2 DDS 跨设备通信配置 ======
export ROS_DOMAIN_ID=6
export ROS_LOCALHOST_ONLY=0
# 以下为可选,不设也行(默认即为 FastDDS)
# export RMW_IMPLEMENTATION=rmw_fastrtps_cpp

最后更新:2026-06-01 | 适用于 ROS2 Humble + FastDDS 默认组播方案

最近更新